/******************************************************************************
 * private.h
 * 
 * Shared structures which are private to the protocol library.
 * 
 * Copyright (c) 1999-2000, K A Fraser
 * 
 * $Id: private.h,v 1.1.1.1 2003/01/14 00:30:55 root Exp $
 */

#ifndef _PRIVATE_H_
#define _PRIVATE_H_

#include "defines.h"
#include "ipv4/ipv4.h"  /* Linux protocol stack public definitions. */

#include "thread.h"
#include "debug.h"
#define SOCK ((pcb) ? (pcb->uid) : (0))
#include "profile.h"

/******************************************************************************
 * Table where we hash connection state on socket id.
 */
#include "hash.h"
extern hash_table_t *pcbs;

/******************************************************************************
 * Some convenient simple type definitions.
 */
#undef TRUE
#undef FALSE
typedef enum {FALSE, TRUE} bool;

/******************************************************************************
 * TCP and UDP: specification of receive and transmit data queues.
 */
#define BUFFERS_PER_RING   1099   // max number of packets in each queue
// MUST be same as ipv4/fake-linux.c: #define NUM_BUFSW 1000

#define BYTES_PER_BUFFER   0x3000 // max number of bytes in each packet

#define TCP_FIFO_SIZE        (BUFFERS_PER_RING * BYTES_PER_BUFFER)
#define TCP_FIFO_GRANULARITY BYTES_PER_BUFFER

//#include "lowlevel.h"

/******************************************************************************
 * Regions in the shared data area.
 */
#define RX_DATA    0 
#define TX_DATA    (RX_DATA + TCP_FIFO_SIZE + TCP_FIFO_GRANULARITY)
#define RX_HEADER  (TX_DATA + TCP_FIFO_SIZE + TCP_FIFO_GRANULARITY)
#define TX_HEADER  (RX_HEADER + BUFFERS_PER_RING * MAX_HEADER_LEN)
#define SHARED_DATA_SIZE (TX_HEADER + BUFFERS_PER_RING * MAX_HEADER_LEN)

#ifdef USE_PTH
extern pthread_mutex_t global_poll_mutex;
extern pthread_cond_t  global_poll_cond;
#else
extern int global_poll_mutex;
extern int global_poll_cond;
#endif

extern __inline__ int min(int a, int b) { return((a<b)?a:b); }
extern __inline__ int max(int a, int b) { return((a>b)?a:b); }

typedef struct mem_block_st mem_block_t;
struct mem_block_st { mem_block_t *next; };
#define ADD_TO_MEM_LIST(__l, __e) ({ (__e)->next = (__l); (__l) = (__e); }) 
#define REMOVE_FROM_MEM_LIST(__l) \
({ mem_block_t *__e; if ( (__e = (__l)) ) (__l) = __e->next; (void *)__e; })

/* A simple set of connection state bits. */
enum { STATE_LOCAL_BOUND=1, STATE_CONNECTED, STATE_LISTENING, STATE_CLOSING};

/* Our wrapper around the socket structure. */
struct user_pcb
{
    /* Miscellaneous state. */
    int uid;         /* Unique identifier for this socket.                */
    int type;        /* The type of socket that we are.                   */
    u32 state;       /* What state we are in.                             */
    int fcntl_flags; /* State returned/set by the `fcntl' interface call. */
    
    /* Information for our yielding algorithm. */
#define PACKETS_PER_YIELD 5
    int recvs_since_upcall;   /* Packets received by BH since call to TH. */
    int sends_since_downcall; /* Packets queued by TH since call to BH.   */

    /* Our view of the data path to the user-safe device. */
//    usd_device_conn_t *usd_conn; -P2
    int usd_conn; // control socket - P2
    caddr_t     shared_data_area;

    /* Our view of the Linux stack. */
    struct u_socket sock; /* connection to top    */
    struct u_sock *sk;    /* connection to bottom */

    /* Buffer management. */
    mem_block_t *tx_free_hdr_list;
    mem_block_t *tx_free_data_list; 
    struct u_sk_buff_head tx_queued_skbuffs;
};

/******************************************************************************
 * Upcall thread creation/deletion functions.
 */
int  init_upcalls();
void kill_upcalls(void);

/******************************************************************************
 * skbuff functions -- called from outside the stack itself.
 */
int init_locked_tx_mem(struct user_pcb *pcb,
                       int num_hdr_bufs,
                       int hdr_size,
                       u_char *hdr_space,
                       int data_size,
                       u_char *data_space);
//int rx_skb(struct user_pcb *pcb);
int rx_skb(char *pkt, int length);
int free_tx_skbs(struct user_pcb *pcb);

struct u_socket *create_new_socket(int protocol);
void free_socket(struct u_socket *sock);
int bind_and_connect_new_socket(struct u_socket *sock,
                                u32 saddr,
                                u16 sport,
                                u32 daddr,
                                u16 dport);



#define IPOPT_OPTVAL 0
#define IPOPT_OLEN   1
#define IPOPT_OFFSET 2
#define IPOPT_MINOFF 4
#define MAX_IPOPTLEN 40
#define IPOPT_NOP IPOPT_NOOP
#define IPOPT_EOL IPOPT_END
#define IPOPT_TS  IPOPT_TIMESTAMP

#define IPOPT_TS_TSONLY         0               /* timestamps only */
#define IPOPT_TS_TSANDADDR      1               /* timestamps and addresses */
#define IPOPT_TS_PRESPEC        3               /* specified modules only */

struct ip_options {
  __u32               faddr;                          /* Saved first hop address */
  unsigned char       optlen;
  unsigned char srr;
  unsigned char rr;
  unsigned char ts;
  unsigned char is_setbyuser:1,                       /* Set by setsockopt?                   */
    is_data:1,                      /* Options in __data, rather than skb   */
    is_strictroute:1,               /* Strict source route                  */
    srr_is_hit:1,                    /* Packet destination addr was our one  */
    is_changed:1,                 /* IP checksum more not valid           */
    rr_needaddr:1,                     /* Need to record addr of outgoing dev  */
    ts_needtime:1,                 /* Need to record timestamp             */
    ts_needaddr:1;                     /* Need to record addr of outgoing dev  */
  unsigned char router_alert;
  unsigned char __pad1;
  unsigned char __pad2;
  unsigned char __data[0];
};


struct inet_skb_parm
{
  struct ip_options   opt;            /* Compiled IP options  */
  u16                 redirport;      /* Redirect port        */
  unsigned char               flags;

#define IPSKB_MASQUERADED       1
#define IPSKB_TRANSLATED        2
#define IPSKB_FORWARDED         4
};


struct tcp_skb_cb {
  union {
    struct inet_skb_parm    h4;
  } header;   /* For incoming frames          */
  __u32               seq;            /* Starting sequence number     */
  __u32               end_seq;        /* SEQ + FIN + SYN + datalen    */
  __u32               when;           /* used to compute rtt's        */
  __u8                flags;          /* TCP header flags.            */

  /* NOTE: These must match up to the flags byte in a                                                                                                                            
   *       real TCP header.                                                                                                                                                      
   */
#define TCPCB_FLAG_FIN          0x01
#define TCPCB_FLAG_SYN          0x02
#define TCPCB_FLAG_RST          0x04
#define TCPCB_FLAG_PSH          0x08
#define TCPCB_FLAG_ACK          0x10
#define TCPCB_FLAG_URG          0x20

  __u8                sacked;         /* State flags for SACK/FACK.   */
#define TCPCB_SACKED_ACKED      0x01    /* SKB ACK'd by a SACK block    */
#define TCPCB_SACKED_RETRANS    0x02    /* SKB retransmitted            */

  __u16               urg_ptr;        /* Valid w/URG flags is set.    */
  __u32               ack_seq;        /* Sequence number ACK'd        */

  __u32 data_seq;
  __u32 end_data_seq;
};

#define TCP_SKB_CB(__skb)       ((struct tcp_skb_cb *)&((__skb)->cb[0]))



#endif _PRIVATE_H_
